#include "IHTTPClient.h"
#include "esp_log.h"
#include <cstring>
#include <esp_http_client.h>
#include <esp_tls.h>
#include <string>

class EspressifHTTPClient : public IHTTPClient {
public:
	EspressifHTTPClient() :
		client(nullptr),
		status_code(0),
		keep_alive(true),
		use_https(false),
		port(0) {}

	~EspressifHTTPClient() {
		stop();
	}

	void setKeepAlive(bool keep_alive) override {
		this->keep_alive = keep_alive;
	}

	int connect(const char *host, uint16_t port) override {
		// 保存主机和端口信息用于后续请求
		this->host = host;
		this->port = port;
		this->use_https = (port == 443); // 443端口默认使用HTTPS

		// 对于ESP-HTTP客户端，我们不在connect时立即建立连接
		// 而是在第一个请求时建立连接
		return 0; // 总是成功，实际连接在perform时建立
	}

	void stop() override {
		if (client) {
			esp_http_client_close(client);
			esp_http_client_cleanup(client);
			client = nullptr;
		}
		status_code = 0;
		response_body.clear();
	}

	int post(const char *url_path, const char *content_type, const char *request_body) override {
		return performRequest(HTTP_METHOD_POST, url_path, content_type, request_body);
	}

	int get(const char *url_path) override {
		return performRequest(HTTP_METHOD_GET, url_path, nullptr, nullptr);
	}

	int getResponseStatusCode() override {
		return status_code;
	}

	std::string getResponseBody() override {
		return response_body;
	}

	// 额外的HTTPS配置方法
	void setHttpsEnabled(bool enabled) override {
		use_https = enabled;
	}

	void setCertificate(const char *cert_pem) override {
		client_cert = cert_pem ? cert_pem : "";
	}

	void setSkipCertVerification(bool skip) override {
		skip_cert_verification = skip;
	}

private:
	int performRequest(esp_http_client_method_t method, const char *url_path,
					   const char *content_type, const char *request_body) {
		// 先停止之前的连接
		stop();

		// 构建完整的URL
		std::string full_url;
		full_url = use_https ? "https://" : "http://";
		full_url += host + ":" + std::to_string(port) + url_path;

		// 配置HTTP客户端
		esp_http_client_config_t config = {};
		config.url = full_url.c_str();
		config.timeout_ms = 10000; // 10秒超时
		config.disable_auto_redirect = false;
		config.keep_alive_enable = keep_alive;
		config.keep_alive_idle = 5;
		config.keep_alive_interval = 5;
		config.method = method;

		// HTTPS 特定配置
		if (use_https) {
			if (!client_cert.empty()) {
				config.cert_pem = client_cert.c_str();
			}
			if (skip_cert_verification) {
				config.skip_cert_common_name_check = true;
				config.auth_type = HTTP_AUTH_TYPE_NONE;
			}
		}

		// 初始化客户端
		client = esp_http_client_init(&config);
		if (!client) {
			return -1;
		}

		// 添加必要的头部
		esp_http_client_set_header(client, "User-Agent", "BeixiangIOT-Client");
		esp_http_client_set_header(client, "Accept", "*/*");
		esp_http_client_set_header(client, "Connection", keep_alive ? "keep-alive" : "close");

		// 设置请求头
		if (content_type) {
			esp_http_client_set_header(client, "Content-Type", content_type);
		}

		// 对于POST请求设置请求体
		if (method == HTTP_METHOD_POST && request_body) {
			esp_http_client_set_post_field(client, request_body, strlen(request_body));
		}
		// 执行请求
		esp_err_t err = esp_http_client_open(client, 0);
		if (err != ESP_OK) {
			stop();
			return -1;
		}
		// 从服务器获取 HTTP 响应头，并准备客户端去读取响应体
		int content_length = esp_http_client_fetch_headers(client);
		if (content_length < 0) {
			ESP_LOGW("", "HTTP GET failed to fetch headers");
		} else {
			ESP_LOGI("", "Content-Length: %d", content_length);
		}

		// 获取状态码
		status_code = esp_http_client_get_status_code(client);

		// 读取响应体
		readResponseBody();

		// 如果不保持连接，立即关闭
		if (!keep_alive) {
			stop();
		}

		return status_code;
	}

	void readResponseBody() {
		response_body.clear();
		int content_length = esp_http_client_get_content_length(client);

		if (content_length > 0) {
			// 对于已知长度的响应
			char *buffer = new char[content_length + 1];
			if (buffer) {
				int read_len = esp_http_client_read_response(client, buffer, content_length);
				if (read_len > 0) {
					buffer[read_len] = '\0';
					response_body.assign(buffer, read_len);
				}
				delete[] buffer;
			}
		} else {
			// 对于chunked编码或未知长度的响应
			char buffer[512];
			int read_len = 0;
			int total_read_len = 0;

			while ((read_len = esp_http_client_read(client, buffer, sizeof(buffer) - 1)) > 0) {
				buffer[read_len] = '\0';
				response_body.append(buffer, read_len);
				total_read_len += read_len;
			}
		}
	}

private:
	esp_http_client_handle_t client;
	int status_code;
	std::string response_body;
	bool keep_alive;
	bool use_https;
	std::string host;
	uint16_t port;
	std::string client_cert;
	bool skip_cert_verification = false;
};